home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers2.zip / SLIP8250.ASM < prev    next >
Assembly Source File  |  1992-01-17  |  23KB  |  911 lines

  1. version    equ    6
  2.  
  3.     include    defs.asm
  4.  
  5. ;Ported from Phil Karn's asy.c and slip.c, a C-language driver for the IBM-PC
  6. ;8250 by Russell Nelson.  Any bugs are due to Russell Nelson.
  7. ;16550 support ruthlessly stolen from Phil Karn's 8250.c. 
  8. ;  Bugs by Denis DeLaRoca
  9. ; Stopped failures from lost transmit interrupts (by eliminating the ints
  10. ; altogether). Remove unneeded transmitter buffer.
  11. ; Version 6 by Joe Doupnik, jrd@cc.usu.edu, Utah State University, Dec 1991.
  12.  
  13. ;  Copyright, 1988, 1991, Russell Nelson
  14.  
  15. ;   This program is free software; you can redistribute it and/or modify
  16. ;   it under the terms of the GNU General Public License as published by
  17. ;   the Free Software Foundation, version 1.
  18. ;
  19. ;   This program is distributed in the hope that it will be useful,
  20. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22. ;   GNU General Public License for more details.
  23. ;
  24. ;   You should have received a copy of the GNU General Public License
  25. ;   along with this program; if not, write to the Free Software
  26. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27.  
  28. code    segment    word public
  29.     assume    cs:code, ds:code
  30.  
  31.     include    8250defs.asm
  32.  
  33. ;Slip Definitions
  34. FR_END        equ    0c0h        ;Frame End
  35. FR_ESC        equ    0dbh        ;Frame Escape
  36. T_FR_END    equ    0dch        ;Transposed frame end
  37. T_FR_ESC    equ    0ddh        ;Transposed frame escape
  38.  
  39.     public    int_no
  40. int_no        db    4,0,0,0        ; interrupt number.
  41. io_addr        dw    03f8h,0        ; I/O address for COM1
  42. baud_rate    dw    12c0h,0        ; support baud higher than 65535
  43. baudclk        label    word
  44.         dd    115200        ; 1.8432 Mhz / 16
  45. hardware_switch    db    0        ; if zero, don't use hw handshaking
  46. is_16550        db      0               ; 0=no, 1=yes (try using fifo)
  47.  
  48.     public    driver_class, driver_type, driver_name 
  49.     public    driver_function, parameter_list
  50. driver_class    db    6,0,0,0        ;from the packet spec
  51. driver_type    db    0,0,0,0        ;from the packet spec
  52. driver_name    db    'SLIP8250',0    ;name of the driver.
  53. driver_function    db    2
  54. parameter_list    label    byte
  55.     db    1    ;major rev of packet driver
  56.     db    9    ;minor rev of packet driver
  57.     db    14    ;length of parameter list
  58.     db    EADDR_LEN    ;length of MAC-layer address
  59.     dw    GIANT    ;MTU, including MAC headers
  60.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  61.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  62.     dw    0    ;(# of successive xmits) - 1
  63. int_num    dw    0    ;Interrupt # to hook for post-EOI
  64.             ;processing, 0 == none,
  65.  
  66.   ifdef debug
  67.     public recv_buf_size, recv_buf,    recv_buf_end, recv_buf_head
  68.     public recv_buf_tail, recv_pkt_ready
  69.   endif
  70. recv_buf_size    dw    3000,0        ;receive buffer size
  71. recv_buf    dw    ?        ;->receive buffer
  72. recv_buf_end    dw    ?        ;->after end of buffer
  73. recv_buf_head    dw    ?        ;->next character to get
  74. recv_buf_tail    dw    ?        ;->next character to store
  75. recv_pkt_ready    dw    0        ; flag indicating a packet is ready
  76. IP_TYPE    DW    0800H
  77.  
  78.   ifdef debug
  79.     public packet_sem, xmit_time
  80.   endif
  81. packet_sem    dw    0        ; semaphore for    packets received
  82. asyrxint_cnt    dw    0        ; loop counter in asyrxint
  83. xmit_time    dw    0        ; loop timer for asyrxint
  84.  
  85.     public    rcv_modes
  86. rcv_modes    dw    4        ;number    of receive modes in our table
  87.         dw    0,0,0,rcv_mode_3
  88.  
  89.  
  90.     public    as_send_pkt
  91. ; The Asynchronous Transmit Packet routine.
  92. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  93. ;   interrupts possibly enabled.
  94. ; Exit with nc if ok, or else cy if error, dh set to error number.
  95. ;   es:di and interrupt enable flag preserved on exit.
  96. as_send_pkt:
  97.     ret
  98.  
  99.     public    drop_pkt
  100. ; Drop a packet from the queue.
  101. ; Enter with es:di -> iocb.
  102. drop_pkt:
  103.     assume    ds:nothing
  104.     ret
  105.  
  106.     public    xmit
  107. ; Process a transmit interrupt with the least possible latency to achieve
  108. ;   back-to-back packet transmissions.
  109. ; May only use ax and dx.
  110. xmit:
  111.     assume    ds:nothing
  112.     ret
  113.  
  114.  
  115.     public    send_pkt
  116. ;
  117. ; mod 7/25/89 John Grover
  118. ; - operates with interrupts on. Xmits one byte per interrupt
  119. ; - only turns transmitter buffer empty interrupt off when
  120. ; - all bytes of all packets are transmitted.
  121.  
  122. send_pkt:
  123. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  124. ;  (only if the high-performance bit is set in driver_function)
  125.  
  126. ;enter with ds:si -> packet, cx = packet length.
  127. ;exit with nc if ok, or else cy if error, dh set to error number.
  128. ;called from telnet layer via software interrupt
  129. ; We just send each byte in turn. No UART interrupts are needed nor wanted.
  130. ; In fact the overdone receiver material omits to note that xmtr interrupts
  131. ; can be lost while processing rcvr ones. Small benefits are no stalled
  132. ; programs, no transmitter buffer, no problems at 19200 b/s. Joe Doupnik
  133.     assume    ds:nothing, es:nothing
  134.     sti                ; enable interrupts
  135.     cld
  136.     mov    al,FR_END        ; Flush out any line garbage
  137.     call    send_char
  138.     jc    send_pkt_end        ; c = failure to send
  139.  
  140. ;Copy input to output, escaping special characters
  141. send_pkt_1:
  142.     lodsb
  143.     cmp    al,FR_ESC      ; escape FR_ESC with FR_ESC and T_FR_ESC
  144.     jne    send_pkt_2
  145.     mov    al,FR_ESC
  146.     call    send_char
  147.     jc    send_pkt_end
  148.     mov    al,T_FR_ESC
  149.     jmp    short send_pkt_3
  150. send_pkt_2:
  151.     cmp    al,FR_END      ; escape FR_END with FR_ESC and T_FR_END
  152.     jne    send_pkt_3
  153.     mov    al,FR_ESC
  154.     call    send_char
  155.     jc    send_pkt_end
  156.     mov    al,T_FR_END
  157. send_pkt_3:
  158.     call    send_char
  159.     jc    send_pkt_end
  160.     loop    send_pkt_1        ; do cx user characters
  161.     mov    al,FR_END        ; terminate it with a FR_END
  162.     call    send_char
  163.     jc    send_pkt_end
  164.     clc
  165. send_pkt_end:
  166.     ret
  167.  
  168. ; mod 7/25/89 John Grover
  169. ; redone by Joe Doupnik, Dec 1991
  170.     assume    ds:nothing, es:nothing
  171. send_char:                ; send the character in al
  172.     push    dx
  173.     push    cx
  174.     xchg    ah,al            ; put data char into ah
  175.     xor    cx,cx            ; 64K retry counter
  176. sendch1:mov    dx,io_addr        ; 03f8h base address
  177.     add    dx,LSR            ; 03fdh get port status
  178.     in    al,dx
  179.     test    al,LSR_THRE        ; Transmitter (THRE) ready?
  180.     jnz    sendch2            ; nz = yes
  181.     jmp    $+2            ; use time, prevent overdriving UART
  182.     jmp    $+2
  183.     loop    sendch1
  184.     stc                ; carry set for failure
  185.     jmp    short sendch3        ; timeout
  186. sendch2:xchg    al,ah            ; now send it
  187.     mov    dx,io_addr        ; 03f8h, use a little time
  188.     jmp    $+2
  189.     out    dx,al            ; send the byte
  190.     clc                ; status of success
  191. sendch3:pop    cx
  192.     pop    dx
  193.     ret
  194.  
  195.  
  196.     public    get_address
  197. get_address:
  198. ;get the address of the interface.
  199. ;enter with es:di -> place to get the address, cx = size of address buffer.
  200. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  201.     assume    ds:code
  202.     xor    cx,cx
  203.     clc
  204.     ret
  205.  
  206.  
  207.     public    set_address
  208. set_address:
  209. ;set the address of the interface.
  210. ;enter with es:di -> place to get the address, cx = size of address buffer.
  211. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  212.     assume    ds:nothing
  213.     clc
  214.     ret
  215.  
  216.  
  217. rcv_mode_3:
  218. ;receive mode 3 is the only one we support, so we don't have to do anything.
  219.     ret
  220.  
  221.  
  222.     public    set_multicast_list
  223. set_multicast_list:
  224. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  225. ;return nc if we set all of them, or cy,dh=error if we didn't.
  226.     mov    dh,NO_MULTICAST
  227.     stc
  228.     ret
  229.  
  230.  
  231.     public    get_multicast_list
  232. get_multicast_list:
  233. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  234. ;return    cy, NO_ERROR if we don't remember all of the addresses ourselves.
  235. ;return cy, NO_MULTICAST if we don't implement multicast.
  236.     mov    dh,NO_MULTICAST
  237.     stc
  238.     ret
  239.  
  240.  
  241.     public    terminate
  242. terminate:
  243.     ret
  244.  
  245.     public    reset_interface
  246. reset_interface:
  247. ;reset the interface.
  248.     assume    ds:code
  249.     ret
  250.  
  251.  
  252. ;called    when we    want to determine what to do with a received packet.
  253. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  254.     extrn    recv_find: near
  255.  
  256. ;called after we have copied the packet into the buffer.
  257. ;enter with ds:si ->the packet, cx = length of the packet.
  258.     extrn    recv_copy: near
  259.  
  260.     extrn    count_in_err: near
  261.     extrn    count_out_err: near
  262.  
  263.     public    recv
  264.  
  265. ;
  266. ; mod 7/25/89 John Grover
  267. ;
  268. ; - added code to check modem status change interrupt. If CTS is
  269. ; - low  turn off transmitter buffer empty interrupt. If CTS is
  270. ; - high turn it on.
  271.  
  272. recv:
  273. ;called from the recv isr.  All registers have been saved, and ds=cs.
  274. ;Upon exit, the interrupt will be acknowledged.
  275.     assume    ds:code
  276. recv_2:
  277.     loadport
  278.     setport    IIR
  279.     in    al,dx            ;any interrupts at all?
  280.     test    al,IIR_IP
  281.     jne    recv_1            ;no.
  282.     and    al,IIR_ID
  283.     cmp    al,IIR_RDA        ;Receiver interrupt
  284.     jne    recv_3
  285.     call    asyrxint
  286.     jmp    recv_2
  287. recv_3:
  288. recv_5:
  289. ;process IIR_MSTAT here.
  290. ;  If CTS and packet ready then
  291. ;    enable the    transmit buffer empty interrupt
  292. ;  else
  293. ;    disable the transmit buffer empty interrupt
  294. ;
  295.     cmp    al, IIR_MSTAT
  296.     jne    recv_1
  297.     setport    MSR            ; make sure of CTS status
  298.     in    al, dx
  299. ;    test    al, MSR_CTS        ; is CTS bit set
  300. ;    jz    recv_5_1        ; no - disable xmit buffer empty int
  301.     jmp    recv_2
  302.  
  303. recv_5_1:
  304.     jmp    recv_2
  305.  
  306. ;process IIR_RLS here
  307. recv_1:
  308.     ret
  309.  
  310.  
  311. ;Process 8250 receiver interrupts
  312. ;
  313. ; mod 7/25/89 John Grover
  314. ; - this branches off when bps < 9600. See asyrxint_a.
  315. ; - Above 9600 bps we go into a loop to process a packet at
  316. ; - a time. If not data ready for a certain amount of time,
  317. ; - the process exits and waits for the next byte. This certain
  318. ; - amount of time to wait depends on the bps and CPU processor speed
  319. ; - and is determined in the initialization of the driver.
  320. ; - Upon receiving the FR_END character for the first frame in the
  321. ; - buffer a semaphore is set which tells recv_frame to run.
  322.  
  323. asyrxint:
  324.  
  325.     push    ds            ; get set up for the routine
  326.     pop    es
  327.     xor    bx, bx
  328.     cmp    baud_rate, 9600         ; below 9600 we're strictly
  329.     jbe    asyrxint_a              ; interrupt driven
  330.     mov    bx, xmit_time
  331. asyrxint_a:
  332.     mov    di,recv_buf_tail
  333.     xor    bp, bp            ; set flag to indicate 1st char
  334.                     ; processed
  335.     mov    si, packet_sem          ; optimization
  336.     loadport
  337.     mov    ah, LSR_DR
  338.  
  339. asyrxint_again:
  340.     xor    cx, cx            ; initialize counter
  341.     setport    LSR
  342. asyrxint_in:
  343.     in    al,dx            ; check for data ready
  344.     test    al,LSR_DR
  345.     jnz    asyrxint_gotit        ; yes - break out of loop
  346.     inc    cx            ; no - increase loop counter
  347.     cmp    cx, bx            ; timeout?
  348.     jae    asyrxint_exit        ; yes - leave
  349.     jmp    asyrxint_in        ; no - keep looping
  350.  
  351. asyrxint_gotit:
  352.     setport    RBR
  353.     in    al,dx
  354.  
  355. ;Process incoming data;
  356. ; If buffer is full, we have no choice but
  357. ; to drop the character
  358.     cmp    di,recv_buf_head    ; check for buffer collision
  359.     jne    asyrxint_ok        ; none - continue
  360.     or    si, si                  ; maybe - if there are packets
  361.     jnz    asyrxint_exit        ; yes exit
  362.  
  363. asyrxint_ok:
  364.     stosb
  365.  
  366.     cmp    di,recv_buf_end        ; did we hit the end of the buffer?
  367.     jne    asyrxint_3        ; no.
  368.     mov    di,recv_buf        ; yes - wrap around.
  369.  
  370. asyrxint_3:
  371.     cmp    al,FR_END        ; might    this be    the end of a frame?
  372.     jne    asyrxint_reset        ; no - reset flag and loop
  373.     inc    si                      ; yes - indicate packet ready
  374.     cmp    si, 1                   ; determine if semaphore is <> 1
  375.     jne    asyrxint_chk_flg        ; yes - recv_frame must be active
  376.     inc    recv_pkt_ready          ; no - set flag to start recv_frame
  377.  
  378. asyrxint_chk_flg:
  379.     cmp    bp, 0                   ; was this the first char?
  380.     jne    asyrxint_1              ; no - exit handler
  381. asyrxint_reset:
  382.     inc    bp            ; set 1st character flag
  383.     jmp    asyrxint_again        ; get another character
  384.  
  385. asyrxint_exit:
  386. asyrxint_1:
  387.     mov    recv_buf_tail,di
  388.     mov    packet_sem, si
  389.  
  390.     ret
  391.  
  392.  
  393. ; --------------------------------------------------------------
  394. ;
  395. ;  recv_exiting
  396. ;
  397.     public    recv_exiting
  398. recv_exiting:
  399.     cmp    recv_pkt_ready, 1       ; is a packet ready?
  400.     jne    recv_isr_exit           ; no - skip to end
  401.     push    ax
  402.     push    bx
  403.     push    cx
  404.     push    dx
  405.     push    ds
  406.     push    es
  407.     push    bp
  408.     push    di
  409.     push    si
  410.     push    cs            ; point ds properly
  411.     pop    ds
  412.     mov    recv_pkt_ready,    0    ; reset flag
  413.     sti                ; enable interrupts
  414.  
  415.     call    recv_frame
  416.  
  417.     cli
  418.     pop    si
  419.     pop    di
  420.     pop    bp
  421.     pop    es
  422.     pop    ds
  423.     pop    dx
  424.     pop    cx
  425.     pop    bx
  426.     pop    ax
  427. recv_isr_exit:
  428.     ret
  429.  
  430.  
  431. ; --------------------------------------------------------------
  432. ;
  433. ;  recv_frame
  434. ;
  435. ; mod 7/25/89 John Grover
  436. ;
  437. ; - recv_frame now operates with interrupts on. It is triggered
  438. ; - by the recv_pkt_ready flag and continues until all bytes
  439. ; - in all packets in the buffer have been transmitted to the upper
  440. ; - layer.
  441. ;
  442.   ifdef debug
  443.     public recv_frame
  444.   endif
  445. recv_frame:
  446.     cmp    packet_sem, 0        ; should we do this?
  447.     jz    recv_frame_end        ; no - exit
  448.     mov    si,recv_buf_head    ;process characters.
  449.     xor    cx,cx            ;count up the size here.
  450. recv_frame_1:
  451.  
  452.     call    recv_char        ;get a char.
  453.     je    recv_frame_2        ;go if no more chars.
  454.     cmp    al,FR_ESC        ;an escape?
  455.     je    recv_frame_1        ;yes - don't count this char.
  456.     inc    cx            ;no - count this one.
  457.     jmp    recv_frame_1
  458. recv_frame_2:
  459.  
  460.     jcxz    recv_frame_3        ;count zero? yes - free the frame
  461. ;we don't need to set the type because none are defined for SLIP.
  462.     push    si            ;save si in case we reject it.
  463.     push    bx
  464.     MOV    DI,CS
  465.     MOV    ES,DI
  466.     mov    di,0
  467.     mov    dl,cs:driver_class
  468.     call    recv_find        ;look up our type.
  469.     pop    bx
  470.     pop    si
  471.  
  472.     mov    ax,es            ;is this pointer null?
  473.     or    ax,di
  474.     je    recv_frame_3        ;yes - just free the frame.
  475.  
  476.     push    cx
  477.     push    es            ;remember where the buffer pointer is
  478.     push    di
  479.  
  480.     mov    si,recv_buf_head    ;process characters.
  481. recv_frame_4:
  482.     call    recv_char
  483.     je    recv_frame_6        ;yes - we're all done.
  484.     cmp    al,FR_ESC        ;an escape?
  485.     jne    recv_frame_5        ;no - just store it.
  486.  
  487.     call    recv_char        ;get the next character.
  488.     je    recv_frame_6
  489.     cmp    al,T_FR_ESC
  490.     mov    al,FR_ESC        ;assume T_FR_ESC
  491.     je    recv_frame_5        ;yup, that's it    - store FR_ESC
  492.     mov    al,FR_END        ;nope, store FR_END
  493. recv_frame_5:
  494.     stosb                ;store the byte.
  495.     jmp    recv_frame_4
  496. recv_frame_6:
  497.     mov    recv_buf_head,si    ;we're skipped to the end.
  498.  
  499.     pop    si            ;now give the frame to the client.
  500.     pop    ds
  501.     pop    cx
  502.     assume    ds:nothing
  503.  
  504.     call    recv_copy
  505.     push    cs
  506.     pop    ds
  507.     assume    ds:code
  508.     jmp    recv_frame_end
  509.  
  510. recv_frame_3:
  511.     mov    recv_buf_head,si    ;remember the new starting point.
  512. recv_frame_end:
  513.     dec    packet_sem
  514.     cmp    packet_sem, 0        ; are there more packets ready?
  515.     ja    recv_frame              ; yes - execute again
  516.     ret
  517.  
  518.  
  519. ; --------------------------------------------------------------
  520. ;
  521. ;  recv_char
  522. ;
  523. ; mod 7/25/89 John Grover
  524. ; - Now    uses buffer pointers to determine if there are
  525. ; - characters left.
  526. ;
  527.  
  528. recv_char:
  529. ;enter with si -> receive buffer, bx = receive count.  Wrap around if needed.
  530. ;return with nz, al = next char.  Return zr if there are no more chars in
  531. ;  this frame.
  532. ;
  533.     lodsb
  534.     cmp    si,recv_buf_end
  535.     jb    recv_char_1
  536.     mov    si,recv_buf
  537. recv_char_1:
  538.     mov    bx, recv_buf_tail
  539.     cmp    si, bx
  540.     je    recv_char_2
  541.     cmp    al,FR_END
  542. recv_char_2:
  543.     ret
  544.  
  545.  
  546. ;Set bit(s) in I/O port
  547. setbit:
  548. ;enter with dx = port, ah = bit to set.
  549.     in    al,dx
  550.     or    al,ah
  551.     out    dx,al
  552.     ret
  553.  
  554.  
  555. ;Clear bit(s) in I/O port
  556. clrbit:
  557. ;enter with dx = port, ah = bit to set.
  558.     in    al,dx
  559.     not    al            ;perform an and-not using DeMorgan's.
  560.     or    al,ah
  561.     not    al
  562.     out    dx,al
  563.     ret
  564.  
  565.  
  566. ;any code after this will not be kept after initialization.
  567. end_resident    label    byte
  568.  
  569.     public    usage_msg
  570. usage_msg    db    "usage: SLIP8250 [-n] [-d] [-w] packet_int_no "
  571.         db    "[-h] [driver_class] [int_no]",CR,LF
  572.         db    "   [io_addr] [baud_rate]",CR,LF
  573.         db    "   [recv_buf_size]",CR,LF
  574.         db    "   -h enables hardware handshaking",CR,LF
  575.         db    "   The driver_class should be SLIP, KISS, AX.25,"
  576.         db    " or a number.",CR,LF,'$'
  577.  
  578.     public    copyright_msg
  579. copyright_msg    db    "Packet driver for SLIP8250, version ",'0'+majver
  580.         db    ".",'0'+version,CR,LF
  581.         db    "Portions Copyright 1988 Phil Karn",CR,LF
  582.         db    "Portions Copyright 1991 Joe Doupnik",cr,lf,'$'
  583.  
  584. approximate_msg    db    "Warning: This baud rate can only be approximated"
  585.         db    "using the 8250",CR,LF
  586.         db    "because it is not an even divisor of 115200"
  587.         db    cr,lf,'$'
  588.  
  589. is_16550_msg    db      "16550 Uart detected, FIFO will be used",CR,LF,'$'
  590.  
  591. class_name_ptr    dw    ?
  592. class_name    db    "Interface class ",'$'
  593. kiss_name    db    "KISS",CR,LF,'$'
  594. ax25_name    db    "AX.25",CR,LF,'$'
  595. slip_name    db    "SLIP",CR,LF,'$'
  596. int_no_name    db    "Interrupt number ",'$'
  597. io_addr_name    db    "I/O port ",'$'
  598. baud_rate_name    db    "Baud rate ",'$'
  599. recv_buf_name    db    "Receive buffer size ",'$'
  600. unusual_com1    db    "That's unusual!  Com1 (0x3f8) usually uses IRQ 4!"
  601.         db    CR,LF,'$'
  602. unusual_com2    db    "That's unusual!  Com2 (0x2f8) usually uses IRQ 3!"
  603.         db    CR,LF,'$'
  604.  
  605.     extrn    set_recv_isr: near
  606.  
  607. ;enter with si -> argument string, di -> word to store.
  608. ;if there is no number, don't change the number.
  609.     extrn    get_number: near
  610.  
  611. ;enter with dx -> name of word, di -> dword to print.
  612.     extrn    print_number: near
  613.  
  614. ;enter with si -> argument string.
  615. ;skip spaces and tabs.  Exit with si -> first non-blank char.
  616.     extrn    skip_blanks: near
  617.  
  618.  
  619.     public    parse_args
  620. parse_args:
  621. ;exit with nc if all went well, cy otherwise.
  622.     call    skip_blanks
  623.     cmp    al,'-'            ;did they specify a switch?
  624.     jne    not_switch
  625.     cmp    byte ptr [si+1],'h'    ;did they specify '-h'?
  626.     je    got_hardware_switch
  627.     stc                ;no, must be an error.
  628.     ret
  629. got_hardware_switch:
  630.     mov    hardware_switch,1
  631.     add    si,2            ;skip past the switch's characters.
  632.     jmp    parse_args        ;go parse more arguments.
  633. not_switch:
  634.     or    al,20h            ; to lower case (assuming letter)
  635.     cmp    al,'k'
  636.     jne    parse_args_2
  637.     mov    driver_class,10        ;KISS, from packet spec
  638.     mov    dx,offset kiss_name
  639.     jmp    short parse_args_1
  640. parse_args_2:
  641.     cmp    al,'s'
  642.     jne    parse_args_3
  643.     mov    driver_class,6        ;SLIP, from packet spec
  644.     mov    dx,offset slip_name
  645.     jmp    short parse_args_1
  646. parse_args_3:
  647.     cmp    al,'a'
  648.     jne    parse_args_4
  649.     mov    driver_class,9        ;AX.25, from packet spec.
  650.     mov    dx,offset ax25_name
  651.     jmp    short parse_args_1
  652. parse_args_4:
  653.     mov    di,offset driver_class
  654.     mov    bx,offset class_name
  655.     call    get_number
  656.     mov    class_name_ptr,0
  657.     jmp    short parse_args_6
  658. parse_args_1:
  659.     mov    class_name_ptr,dx
  660. parse_args_5:
  661.     mov    al,[si]            ;skip to the next blank or CR.
  662.     cmp    al,' '
  663.     je    parse_args_6
  664.     cmp    al,CR
  665.     je    parse_args_6
  666.     inc    si            ;skip the character.
  667.     jmp    parse_args_5
  668. parse_args_6:
  669.     mov    di,offset int_no
  670.     call    get_number
  671.     mov    di,offset io_addr
  672.     call    get_number
  673.     mov    di,offset baud_rate
  674.     call    get_number
  675.     mov    di,offset recv_buf_size
  676.     call    get_number
  677.     clc
  678.     ret
  679.  
  680.  
  681. ; --------------------------------------------------------------
  682. ;
  683. ;  etopen
  684. ;
  685. ; mod 7/25/89 John Grover
  686. ; - Contains a loop to determine a pseudo timeout for asyrxint.
  687. ; - The value is determined by transmitting characters in a
  688. ; - loop whose clock cycles are nearly the same as the "sister"
  689. ; - loop in asyrxint. The per character, maximum time used
  690. ; - basis which is then multiplied by a factor to achieve a timeout
  691. ; - value for the particular bps and CPU speed of the host.
  692.  
  693.     public    etopen
  694. etopen:
  695.     pushf
  696.     cli
  697. ;
  698. ; mod  3/16/90  Denis DeLaRoca
  699. ; - determine if 16550 uart is present
  700. ; - if so initialize fifo buffering
  701. ;
  702.     loadport
  703.     setport    FCR
  704.     mov    al,FIFO_ENABLE
  705.     out    dx,al                   ;outportb(base+FCR,(char) FIFO_ENABLE)
  706.     setport    IIR
  707.     in    al,dx                   ;inportb(base+IIR)
  708.     and    al,IIR_FIFO_ENABLED     ;     & IIR_FIFO_ENABLED
  709.     cmp    al,IIR_FIFO_ENABLED    ;both bits must be on   NEW, 11/20/90
  710.     jnz    not_16550               ;nope, we don't have 16550 chip
  711.     mov    is_16550,1              ;yes, note fact
  712.     mov    al,FIFO_SETUP           ;and setup FIFO
  713.     setport    FCR
  714.     out    dx,al                   ;outportb(base+FCR,(char) FIFO_SETUP)
  715.  
  716.     mov    dx,offset is_16550_msg
  717.     mov    ah,9
  718.     int    21h            ;let user know about 16550
  719.  
  720. not_16550:
  721.     loadport            ;Purge the receive data buffer
  722.     setport    RBR
  723.     in    al,dx
  724.  
  725.     ;Set line control register: 8 bits, no parity
  726.     mov    al,LCR_8BITS
  727.     setport    LCR
  728.     out    dx,al
  729.  
  730.     ;Turn on receive interrupt enable in 8250, leave transmit
  731.     ; and modem status interrupts turned off for now
  732.     mov    al,IER_DAV
  733.     setport    IER
  734.     out    dx,al
  735.  
  736.     ;Set modem control register: assert DTR, RTS, turn on 8250
  737.     ; master interrupt enable (connected to OUT2)
  738.  
  739.     mov    al,MCR_DTR or MCR_RTS or MCR_OUT2
  740.     setport    MCR
  741.     out    dx,al
  742.  
  743. ;compute the divisor given the baud rate.
  744.     mov    dx,baudclk+2
  745.     mov    ax,baudclk
  746.     mov    bx,0
  747. asy_speed_1:
  748.     inc    bx
  749.     sub    ax,baud_rate
  750.     sbb    dx,baud_rate+2
  751.     jnc    asy_speed_1
  752.     dec    bx
  753.     add    ax,baud_rate
  754.     adc    dx,baud_rate+2
  755.     or    ax,dx
  756.     je    asy_speed_2
  757.  
  758.     mov    dx,offset approximate_msg
  759.     mov    ah,9
  760.     int    21h
  761.  
  762. asy_speed_2:
  763.  
  764.     loadport            ;Purge the receive data buffer
  765.     setport    RBR
  766.     in    al,dx
  767.  
  768.     mov    ah,LCR_DLAB        ;Turn on divisor latch access bit
  769.     setport    LCR
  770.     call    setbit
  771.  
  772.     mov    al,bl            ;Load the two bytes of the divisor.
  773.     setport    DLL
  774.     out    dx,al
  775.     mov    al,bh
  776.     setport    DLM
  777.     out    dx,al
  778.  
  779.     mov    ah,LCR_DLAB        ;Turn off divisor latch access bit
  780.     setport    LCR
  781.     call    clrbit
  782.  
  783.     call    set_recv_isr        ;Set interrupt vector to SIO handler
  784.  
  785. ;set up the various pointers.
  786.     mov    dx,offset end_resident
  787.  
  788.     mov    recv_buf,dx
  789.     mov    recv_buf_head,dx
  790.     mov    recv_buf_tail,dx
  791.     add    dx,recv_buf_size
  792.     mov    recv_buf_end,dx
  793.     push    dx            ;save the ending address.
  794.  
  795.     ; the following code attempts to determine a pseudo timeout
  796.     ; value    to use in the loop that waits for an incoming character
  797.     ; in asyrxint. The value returned in xmit_time is the number of
  798.     ; loops processed between characters - therefore the loop used below
  799.     ; is and should    remain similar to the loop used in asyrxint.
  800.  
  801.     xor    ax, ax            ; we'll send a 0
  802.     mov    ah, LSR_THRE
  803.     mov    cx, 10h            ; take the highest of 16 runs
  804.     xor    si, si            ; will hold highest value
  805.  
  806. xmit_time_start:
  807.  
  808.     xor    di, di            ; initialize counter
  809.     loadport
  810.     setport    THR            ; xmit a character
  811.     out    dx, al
  812.     setport    LSR               ; set up    to check for an empty buffer
  813.  
  814.     ; next is the loop actually being timed
  815.  
  816. xmit_time_top:
  817.     in    al, dx
  818.     test    al, ah
  819.     jnz    xmit_time_done
  820.     inc    di
  821.     cmp    cx, cx            ; these next few instructions do nothing
  822.     jmp    xmit_time_1        ;  except maintain similarity with the
  823.                     ;  "sister" loop in asyrxint
  824. xmit_time_1:
  825.     jmp    xmit_time_top
  826.  
  827. xmit_time_done:                ; end of timed loop
  828.  
  829.  
  830.  
  831.     cmp    si, di            ; compare highest value with new value
  832.     ja    xmit_time_end        ; no bigger - just loop
  833.     mov    si, di            ; bigger - save it
  834.  
  835. xmit_time_end:
  836.     loop    xmit_time_start        ; bottom of outer loop
  837.  
  838.     shl    si, 1            ; we'll wait 8 characters worth
  839.     shl    si, 1
  840.     shl    si, 1
  841.     mov    xmit_time, si        ; retain largest value
  842.  
  843.     ; end of pseudo timer determination
  844.  
  845.     mov    al, int_no        ; Get board's interrupt vector
  846.     add    al, 8
  847.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  848.     jb    set_int_num        ; No.
  849.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  850. set_int_num:
  851.     xor    ah, ah            ; Clear high byte
  852.     mov    int_num, ax        ; Set parameter_list int num.
  853.  
  854.     pop    dx            ;return the ending address.
  855.     popf
  856.     clc                ;indicate no errors.
  857.     ret
  858.  
  859.     public    print_parameters
  860. print_parameters:
  861. ;echo our command-line parameters
  862.     cmp    class_name_ptr,0
  863.     je    echo_args_1
  864.  
  865.     mov    dx,offset class_name
  866.     mov    ah,9
  867.     int    21h
  868.     mov    dx,class_name_ptr
  869.     mov    ah,9
  870.     int    21h
  871.     jmp    short echo_args_2
  872. echo_args_1:
  873.     mov    di,offset driver_class
  874.     mov    dx,offset class_name
  875.     call    print_number
  876. echo_args_2:
  877.  
  878.     mov    di,offset int_no
  879.     mov    dx,offset int_no_name
  880.     call    print_number
  881.     mov    di,offset io_addr
  882.     mov    dx,offset io_addr_name
  883.     call    print_number
  884.  
  885.     cmp    io_addr,03f8h        ;is this com1?
  886.     jne    ia_com2
  887.     mov    dx,offset unusual_com1
  888.     cmp    int_no,4        ;com1 usually uses IRQ 4.
  889.     jne    ia_unusual
  890.     jmp    short ia_usual
  891. ia_com2:
  892.     cmp    io_addr,02f8h        ;is this com2?
  893.     jne    ia_usual        ;no.
  894.     mov    dx,offset unusual_com2
  895.     cmp    int_no,3        ;com2 usually uses IRQ 3.
  896.     je    ia_usual
  897. ia_unusual:
  898.     mov    ah,9
  899.     int    21h
  900. ia_usual:
  901.     mov    di,offset baud_rate
  902.     mov    dx,offset baud_rate_name
  903.     call    print_number
  904.     mov    di,offset recv_buf_size
  905.     mov    dx,offset recv_buf_name
  906.     call    print_number
  907.     ret
  908. code    ends
  909.     end
  910.  
  911.